//
// Copyright (C) 2011 - 2013  Steve Channell steve.channell@cepheis.com
//
// This file is part of Cephei.QL, an open-source library wrapper 
// arround QuantLib http://quantlib.org/
//
// Cephei.QL is open source software: you can redistribute it and/or modify it
// under the terms of the license.  You should have received a
// copy of the license along with this program; if not, please email
// <support@cepheis.com>. The license is also available online at
// <http://cepheis.com/license.htm>.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the license for more details.
//
// Version 2.2 with QuantLib 1.2.1
//#include "stdafx.h"
#include "GemanRoncoroniProcess.h"
using namespace Cephei::QL::Experimental::Processes;
#include <gen/QL/Math/Array.h>
#include <gen/QL/StochasticProcess1D.h>
using namespace Cephei::QL::Math;
using namespace Cephei::QL;
#define HANDLE
#undef ABSTRACT
#undef STRUCT
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (Double x0, Double alpha, Double beta, Double gamma, Double delta, Double eps, Double zeta, Double d, Double k, Double tau, Double sig2, Double a, Double b, Double theta1, Double theta2, Double theta3, Double psi) : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
    try
    {
#ifdef HANDLE
        _phGemanRoncoroniProcess = NULL;
#endif
        QuantLib::Real _x0 = (QuantLib::Real)ValueHelper::Convert (x0); //d
        QuantLib::Real _alpha = (QuantLib::Real)ValueHelper::Convert (alpha); //d
        QuantLib::Real _beta = (QuantLib::Real)ValueHelper::Convert (beta); //d
        QuantLib::Real _gamma = (QuantLib::Real)ValueHelper::Convert (gamma); //d
        QuantLib::Real _delta = (QuantLib::Real)ValueHelper::Convert (delta); //d
        QuantLib::Real _eps = (QuantLib::Real)ValueHelper::Convert (eps); //d
        QuantLib::Real _zeta = (QuantLib::Real)ValueHelper::Convert (zeta); //d
        QuantLib::Real _d = (QuantLib::Real)ValueHelper::Convert (d); //d
        QuantLib::Real _k = (QuantLib::Real)ValueHelper::Convert (k); //d
        QuantLib::Real _tau = (QuantLib::Real)ValueHelper::Convert (tau); //d
        QuantLib::Real _sig2 = (QuantLib::Real)ValueHelper::Convert (sig2); //d
        QuantLib::Real _a = (QuantLib::Real)ValueHelper::Convert (a); //d
        QuantLib::Real _b = (QuantLib::Real)ValueHelper::Convert (b); //d
        QuantLib::Real _theta1 = (QuantLib::Real)ValueHelper::Convert (theta1); //d
        QuantLib::Real _theta2 = (QuantLib::Real)ValueHelper::Convert (theta2); //d
        QuantLib::Real _theta3 = (QuantLib::Real)ValueHelper::Convert (theta3); //d
        QuantLib::Real _psi = (QuantLib::Real)ValueHelper::Convert (psi); //d
        _ppGemanRoncoroniProcess = new boost::shared_ptr<QuantLib::GemanRoncoroniProcess> (new QuantLib::GemanRoncoroniProcess ( _x0,  _alpha,  _beta,  _gamma,  _delta,  _eps,  _zeta,  _d,  _k,  _tau,  _sig2,  _a,  _b,  _theta1,  _theta2,  _theta3,  _psi ));
        SetStochasticProcess1D (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (boost::shared_ptr<QuantLib::GemanRoncoroniProcess>& childNative, Object^ owner) : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
#ifdef HANDLE
	_phGemanRoncoroniProcess = NULL;
#endif
	_ppGemanRoncoroniProcess = &childNative;
    _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
}
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (QuantLib::GemanRoncoroniProcess& childNative, Object^ owner) : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
#ifdef HANDLE
	_phGemanRoncoroniProcess = NULL;
#endif
	_ppGemanRoncoroniProcess = new boost::shared_ptr<QuantLib::GemanRoncoroniProcess> (&childNative);
    _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
    _GemanRoncoroniProcessOwner = owner;
    _StochasticProcess1DOwner = owner;
}

Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (CGemanRoncoroniProcess^ copy) : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
#ifdef HANDLE
	_phGemanRoncoroniProcess = NULL;
#endif
	if (copy->HasNative() != NULL)
    {
		_ppGemanRoncoroniProcess = new boost::shared_ptr<QuantLib::GemanRoncoroniProcess> (copy->GetShared());
        _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
    }
}
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (PLATFORM::Type^ t) : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
#ifdef HANDLE
	_phGemanRoncoroniProcess = NULL;
#endif
	if (!t->IsSubclassOf(CGemanRoncoroniProcess::typeid))
		throw REFNEW Exception ("Invalid base-case init");
}
#ifdef HANDLE
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (QuantLib::Handle<QuantLib::GemanRoncoroniProcess>& childNative, Object^ owner)  : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
	_phGemanRoncoroniProcess = &childNative;
	_ppGemanRoncoroniProcess = &static_cast<boost::shared_ptr<QuantLib::GemanRoncoroniProcess>>(childNative.currentLink());
    _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
    _GemanRoncoroniProcessOwner = owner;
}
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (QuantLib::Handle<QuantLib::GemanRoncoroniProcess> childNative)  : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
	_phGemanRoncoroniProcess = &childNative;
	_ppGemanRoncoroniProcess = &static_cast<boost::shared_ptr<QuantLib::GemanRoncoroniProcess>>(childNative.currentLink());
    _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
}
#endif
#ifdef STRUCT
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::CGemanRoncoroniProcess (QuantLib::GemanRoncoroniProcess childNative)  : CStochasticProcess1D(CGemanRoncoroniProcess::typeid)
{
#ifdef HANDLE
	_phGemanRoncoroniProcess = NULL;
#endif
	_ppGemanRoncoroniProcess = new boost::shared_ptr<QuantLib::GemanRoncoroniProcess> (new QuantLib::GemanRoncoroniProcess (childNative));
    _ppStochasticProcess1D = new boost::shared_ptr<QuantLib::StochasticProcess1D> (boost::dynamic_pointer_cast<QuantLib::StochasticProcess1D> (*_ppGemanRoncoroniProcess));
}
#endif

Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::~CGemanRoncoroniProcess ()
{
    if (_ppGemanRoncoroniProcess != NULL)
    {
	    delete _ppGemanRoncoroniProcess;
        _ppGemanRoncoroniProcess = NULL;
    }
}
Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::!CGemanRoncoroniProcess ()
{
    if (_ppGemanRoncoroniProcess != NULL)
    {
	    delete _ppGemanRoncoroniProcess;
    }
}
QuantLib::GemanRoncoroniProcess& Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::GetReference ()
{
    if (_ppGemanRoncoroniProcess == NULL) throw REFNEW NativeNullException ();
	return **_ppGemanRoncoroniProcess;
}
boost::shared_ptr<QuantLib::GemanRoncoroniProcess>& Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::GetShared ()
{
    if (_ppGemanRoncoroniProcess == NULL) throw REFNEW NativeNullException ();
	return *_ppGemanRoncoroniProcess;
}
QuantLib::GemanRoncoroniProcess* Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::GetPointer ()
{
    if (_ppGemanRoncoroniProcess == NULL) throw REFNEW NativeNullException ();
	return &**_ppGemanRoncoroniProcess;
}
#ifdef HANDLE
QuantLib::Handle<QuantLib::GemanRoncoroniProcess>& Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::GetHandle ()
{
	if (_phGemanRoncoroniProcess == NULL)
	{
		_phGemanRoncoroniProcess = new Handle<QuantLib::GemanRoncoroniProcess> (*_ppGemanRoncoroniProcess);
	}
	return *_phGemanRoncoroniProcess;
}
#endif
bool Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::HasNative () 
{
	return (_ppGemanRoncoroniProcess != NULL);
}

Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::Diffusion (Double t, Double x)
{
    try
    {
        QuantLib::Time _t = (QuantLib::Time)ValueHelper::Convert (t); //a
        QuantLib::Real _x = (QuantLib::Real)ValueHelper::Convert (x); //a
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->diffusion ( _t,  _x );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::Drift (Double t, Double x)
{
    try
    {
        QuantLib::Time _t = (QuantLib::Time)ValueHelper::Convert (t); //a
        QuantLib::Real _x = (QuantLib::Real)ValueHelper::Convert (x); //a
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->drift ( _t,  _x );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::Evolve (Double t0, Double x0, Double dt, Double dw, Cephei::QL::Math::IArray^ du)
{
    CArray^ _Cdu;
    try
    {
        QuantLib::Time _t0 = (QuantLib::Time)ValueHelper::Convert (t0); //a
        QuantLib::Real _x0 = (QuantLib::Real)ValueHelper::Convert (x0); //a
        QuantLib::Time _dt = (QuantLib::Time)ValueHelper::Convert (dt); //a
        QuantLib::Real _dw = (QuantLib::Real)ValueHelper::Convert (dw); //a
        _Cdu = safe_cast<CArray^> (du);
        _Cdu->Lock();
        QuantLib::Array& _du = static_cast<QuantLib::Array&> (_Cdu->GetReference ()); 
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->evolve ( _t0,  _x0,  _dt,  _dw,  _du );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
        if (_Cdu != nullptr) _Cdu->Unlock();
    }
}
Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::Evolve (Double t0, Double x0, Double dt, Double dw)
{
    try
    {
        QuantLib::Time _t0 = (QuantLib::Time)ValueHelper::Convert (t0); //a
        QuantLib::Real _x0 = (QuantLib::Real)ValueHelper::Convert (x0); //a
        QuantLib::Time _dt = (QuantLib::Time)ValueHelper::Convert (dt); //a
        QuantLib::Real _dw = (QuantLib::Real)ValueHelper::Convert (dw); //a
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->evolve ( _t0,  _x0,  _dt,  _dw );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::StdDeviation (Double t0, Double x0, Double dt)
{
    try
    {
        QuantLib::Time _t0 = (QuantLib::Time)ValueHelper::Convert (t0); //a
        QuantLib::Real _x0 = (QuantLib::Real)ValueHelper::Convert (x0); //a
        QuantLib::Time _dt = (QuantLib::Time)ValueHelper::Convert (dt); //a
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->stdDeviation ( _t0,  _x0,  _dt );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Double Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess::X0::get ()
{
    try
    {
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppGemanRoncoroniProcess)->x0 ( );   
        Double _nrv = (Double)ValueHelper::Convert (_rv); //c
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String(_error.what()));
        else
		    throw REFNEW NativeExcpetion (REFNEW PLATFORM::String("Unknown std::exception"));
	}
    finally
    {
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Factory class

Cephei::QL::Experimental::Processes::IGemanRoncoroniProcess^ Cephei::QL::Experimental::Processes::CGemanRoncoroniProcess_Factory::Create (Double x0, Double alpha, Double beta, Double gamma, Double delta, Double eps, Double zeta, Double d, Double k, Double tau, Double sig2, Double a, Double b, Double theta1, Double theta2, Double theta3, Double psi)
{
    return REFNEW CGemanRoncoroniProcess ( x0,  alpha,  beta,  gamma,  delta,  eps,  zeta,  d,  k,  tau,  sig2,  a,  b,  theta1,  theta2,  theta3,  psi);
}
